home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol07 / 03 / drag / dfserver.c < prev    next >
Text File  |  1992-05-01  |  16KB  |  425 lines

  1. /****************************************************************************
  2. Module name: DFServer.C
  3. Programmer : Jeffrey M. Richter.
  4. Description: Drop File Server Sample Application.
  5. *****************************************************************************/
  6.  
  7. #include <windows.h>
  8. #include <shellapi.h>
  9. #include <commdlg.h>
  10. #include <string.h>
  11.  
  12. #include "DFServer.h"
  13.  
  14. //************ PROTOTYPES FOR FILE OPEN UTILITY FUNCTION ********************/
  15. WORD FAR GetSinglePathName (LPCSTR szFileOpenStr, WORD wIndex,
  16.         LPSTR szPathName, WORD wMaxLen);
  17.  
  18.  
  19. //************ PROTOTYPES FOR DROP-FILE SERVER FUNCTIONS ********************/
  20. HDROP FAR DragCreateFiles (LPPOINT lpptMousePos, BOOL fInNonClientArea);
  21. HDROP FAR DragAppendFile (HDROP hDrop, LPCSTR szPathname);
  22.  
  23.  
  24. //****************** PROTOTYPES FOR LOCAL FUNCTIONS *************************/
  25. LRESULT FAR WndProc (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
  26. #define UM_UPDATECAPTION        (WM_USER + 0)    // wParam is number of files
  27.  
  28. //************************ GLOBAL VARIABLES *********************************/
  29. char _szAppName[] = "Drop File Server";
  30. extern _cdecl HINSTANCE _hInstance;
  31.  
  32.  
  33. #pragma argsused
  34. int WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  35.         LPSTR lpszCmdLine, int nCmdShow) {
  36.  
  37.         MSG msg;
  38.         HWND hWnd;
  39.         WNDCLASS wc;
  40.  
  41.         if (hPrevInstance == NULL) {
  42.                 wc.style = 0;
  43.                 wc.lpfnWndProc = (WNDPROC) WndProc;
  44.                 wc.cbClsExtra = wc.cbWndExtra = 0;
  45.                 _hInstance = wc.hInstance = hInstance;
  46.                 wc.hIcon = LoadIcon(hInstance, "DropFile");
  47.                 wc.hCursor = LoadCursor(NULL, IDC_UPARROW);
  48.                 wc.hbrBackground = COLOR_GRAYTEXT + 1;
  49.                 wc.lpszMenuName = "DROPFILE";
  50.                 wc.lpszClassName = _szAppName;
  51.                 if (!RegisterClass(&wc)) return(0);
  52.         }
  53.  
  54.         // Create the Frame window.
  55.         // The WS_EXACCEPTFILES style is not needed for server-only apps.
  56.         hWnd = CreateWindow(_szAppName, _szAppName,
  57.                 WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME |
  58.                 WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
  59.                 CW_USEDEFAULT, nCmdShow,
  60.                 GetSystemMetrics(SM_CXSCREEN) / 2,      // 1/2-screen width
  61.                 GetSystemMetrics(SM_CYSCREEN) / 8,      // 1/8-screen height
  62.                 NULL, NULL, hInstance, NULL);
  63.         if (hWnd == NULL) return(0);
  64.  
  65.         while (GetMessage(&msg, NULL, 0, 0)) {
  66.                 TranslateMessage(&msg);
  67.                 DispatchMessage(&msg);
  68.         }
  69.         return(msg.wParam);
  70. }
  71.  
  72.  
  73. LRESULT FAR WndProc (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
  74.         static char szAllFileNames[1000]  = { 0 };
  75.         HCURSOR hCrsrDrpNotAllow, hCrsrDrpSingle, hCrsrDrpMultiple;
  76.         char szBuf[100], szDropPathName[200];
  77.         BOOL fCallDefProc = FALSE, fInNonClientArea, fOkToDrop;
  78.         LONG lResult = 0;
  79.         POINT ptMousePos;
  80.         WORD x, wNumFiles;
  81.         HWND hWndSubject;
  82.         HDROP hDrop, hDropT;
  83.         OPENFILENAME ofn;
  84.  
  85.  
  86.         switch (Msg) {
  87.                 case WM_CREATE:
  88.                         SendMessage(hWnd, UM_UPDATECAPTION, 0, 0);
  89.                         break;
  90.  
  91.                 case WM_DESTROY:
  92.                         // Terminate the application
  93.                         PostQuitMessage(0);
  94.                         break;
  95.  
  96.                 case WM_COMMAND:
  97.                         if (wParam != IDM_FILESELECT) {
  98.                                 fCallDefProc = TRUE;
  99.                                 break;
  100.                         }
  101.  
  102.                         // Initialize structure for calling
  103.                         // the "Open File" common dialog
  104.                         _fmemset(&ofn, 0, sizeof(ofn));
  105.                         ofn.lStructSize = sizeof(ofn);
  106.                         ofn.hwndOwner = hWnd;
  107.                         ofn.lpstrFilter = "All files\0*.*\0";
  108.                         ofn.Flags = OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST |
  109.                                     OFN_HIDEREADONLY;
  110.  
  111.                         // Set up the buffer to receive the selected file(s)
  112.                         szAllFileNames[0] = 0;
  113.                         ofn.lpstrFile = szAllFileNames;
  114.                         ofn.nMaxFile = sizeof(szAllFileNames);
  115.  
  116.                         if (GetOpenFileName(&ofn))
  117.                                 wNumFiles = GetSinglePathName(szAllFileNames,
  118.                                                               -1, NULL, 0);
  119.                         else
  120.                              wNumFiles = 0;
  121.                         SendMessage(hWnd, UM_UPDATECAPTION, wNumFiles, 0);
  122.                         break;
  123.  
  124.                 case UM_UPDATECAPTION:
  125.                         // Update the window's caption to reflect the # of
  126.                         // selected files
  127.                         wsprintf(szBuf, "%s - %d file(s) to drop",
  128.                                 (LPSTR) _szAppName, wParam);
  129.                         SetWindowText(hWnd, szBuf);
  130.                         break;
  131.  
  132.                 case WM_LBUTTONDOWN:
  133.                         // User has initiated the "Drag and Drop" sequence
  134.  
  135.                         // Make sure that there are some selected files
  136.                         // to be dropped
  137.                         wNumFiles = GetSinglePathName(szAllFileNames, -1,
  138.                                                       NULL, 0);
  139.                         if (wNumFiles == 0)
  140.                            {
  141.                            MessageBox(hWnd, "No files to drop.",
  142.                                       _szAppName, MB_OK);
  143.                            break;
  144.                            }
  145.  
  146.                         // Get the handles to the cursors that
  147.                         // will shown to the user.
  148.                         hCrsrDrpNotAllow = LoadCursor(_hInstance,
  149.                                                       "DRPFIL_NOTALLOWED");
  150.                         hCrsrDrpSingle   = LoadCursor(_hInstance,
  151.                                                       "DRPFIL_SINGLE");
  152.                         hCrsrDrpMultiple = LoadCursor(_hInstance,
  153.                                                       "DRPFIL_MULTIPLE");
  154.  
  155.  
  156.                         // *** Loop for determining the drop-file
  157.                         //     client window ***
  158.                         SetCapture(hWnd);
  159.                         do {
  160.                             // Get cursor pos. & window under the cursor
  161.                             GetCursorPos(&ptMousePos);
  162.                             hWndSubject = WindowFromPoint(ptMousePos);
  163.  
  164.                             if (!IsWindow(hWndSubject) ||
  165.                                 !(GetWindowLong(hWndSubject, GWL_EXSTYLE) &
  166.                                   WS_EX_ACCEPTFILES))
  167.                                 {
  168.                                 fOkToDrop = FALSE;
  169.                                 SetCursor(hCrsrDrpNotAllow);
  170.                                 }
  171.                             else
  172.                                 {
  173.                                 fOkToDrop = TRUE;
  174.                                 SetCursor((wNumFiles > 1) ?
  175.                                           hCrsrDrpMultiple : hCrsrDrpSingle);
  176.                                 }
  177.  
  178.                             // Terminate loop when mouse button is released
  179.                         } while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
  180.                         ReleaseCapture();
  181.  
  182.                         // Free the loaded cursors from memory
  183.                         DestroyCursor(hCrsrDrpNotAllow);
  184.                         DestroyCursor(hCrsrDrpSingle);
  185.                         DestroyCursor(hCrsrDrpMultiple);
  186.  
  187.  
  188.                         if (!fOkToDrop) break;
  189.  
  190.                         // Is the cursor in the window's non-client area?
  191.                         fInNonClientArea = (HTCLIENT !=
  192.                                 SendMessage(hWndSubject, WM_NCHITTEST, 0,
  193.                                 (LONG) MAKELONG(ptMousePos.x, ptMousePos.y)));
  194.  
  195.  
  196.                         // Create drop-file memory block and initialize it
  197.                         ScreenToClient(hWndSubject, &ptMousePos);
  198.                         hDrop = DragCreateFiles(&ptMousePos, fInNonClientArea);
  199.                         if (hDrop == NULL)
  200.                            {
  201.                            MessageBox(hWnd,
  202.                                       "Insufficient memory to drop file(s).",
  203.                                       _szAppName, MB_OK);
  204.                            break;
  205.                            }
  206.  
  207.  
  208.                         // *** Append each full pathname to
  209.                         //     the drop-file memory block ***
  210.                         for (x = 0; x < wNumFiles; x++)
  211.                             {
  212.                             GetSinglePathName(szAllFileNames, x,
  213.                                     szDropPathName, sizeof(szDropPathName));
  214.  
  215.                             // Append pathname to end of drop-file memory block
  216.                             hDropT = DragAppendFile(hDrop, szDropPathName);
  217.  
  218.                             if (hDropT == NULL)
  219.                                {
  220.                                MessageBox(hWnd,
  221.                                          "Insufficient memory to drop file(s).",
  222.                                          _szAppName, MB_OK);
  223.                                GlobalFree(hDrop);
  224.                                hDrop = NULL;
  225.                                break;  // Terminate while loop
  226.                                }
  227.                             else
  228.                                {
  229.                                hDrop = hDropT;
  230.                                }
  231.                             }
  232.  
  233.                         if (hDrop != NULL)
  234.                            {
  235.                            // All pathnames appended successfully,
  236.                            // post the message
  237.                            // to the drop-file client window
  238.                            PostMessage(hWndSubject, WM_DROPFILES, hDrop, 0L);
  239.  
  240.                            // Clear our own state
  241.                            szAllFileNames[0] = 0;
  242.                            SendMessage(hWnd, UM_UPDATECAPTION, 0, 0);
  243.  
  244.                            // Don't free the memory,
  245.                            // the Dropfile client will do it
  246.                            }
  247.                         break;
  248.  
  249.                 default:
  250.                    fCallDefProc = TRUE;
  251.                    break;
  252.         }
  253.  
  254.         if (fCallDefProc)
  255.            lResult = DefWindowProc(hWnd, Msg, wParam, lParam);
  256.  
  257.         return(lResult);
  258. }
  259.  
  260.  
  261. /****************************************************************************/
  262. /**********************                            **************************/
  263. /********************** FILE OPEN UTILITY FUNCTION **************************/
  264. /**********************                            **************************/
  265. /****************************************************************************/
  266.  
  267. WORD FAR GetSinglePathName (LPCSTR szFileOpenStr, WORD wIndex,
  268.                             LPSTR szPathName, WORD wMaxLen)
  269. {
  270.  
  271.     WORD wNumFiles = 0, x, y;
  272.     LPCSTR p = szFileOpenStr, q;
  273.     char szBuf[200];
  274.  
  275.     // Initialize the buffer by clearing it
  276.     _fmemset(szBuf, 0, sizeof(szBuf));
  277.  
  278.     // Calculate the number of files in szFileOpenStr
  279.     while (*p)
  280.        {
  281.        if (*p == ' ') wNumFiles++;
  282.        p++;
  283.        }
  284.  
  285.     // If a single file was selected, there are no spaces but we
  286.     // should return that one file exists
  287.     if ((wNumFiles == 0) && (p != szFileOpenStr))
  288.         wNumFiles = 1;
  289.  
  290.     // If the user only wants the number of files, return that
  291.     if ((int) wIndex == -1)
  292.        return(wNumFiles);
  293.  
  294.     // User requested more files than exist
  295.     if (wIndex > wNumFiles)
  296.        return(0);
  297.  
  298.     // *** Construct the full pathname of the requested string ***
  299.     if ((wIndex == 0) && (wNumFiles == 1))
  300.        {
  301.        _fstrncpy(szBuf, szFileOpenStr, wMaxLen);
  302.        }
  303.     else
  304.        {
  305.        // Copy the path portion of the string into a temp buffer
  306.        x = (WORD) ((p = _fstrchr(szFileOpenStr, ' ')) - szFileOpenStr);
  307.        _fstrncpy(szBuf, szFileOpenStr, x);
  308.  
  309.        // Append a backslash if necessary
  310.        if (*(p - 1) != '\\')
  311.           {
  312.           szBuf[x] = '\\';
  313.           x++;
  314.           }
  315.  
  316.        for (y = 0; y < wIndex; y++)
  317.            {
  318.            p++;    // Increment past the space, 'p' points to proper filename
  319.            while (*p != ' ') p++;
  320.            }
  321.        p++;        // Increment past the space, 'p' points to proper filename
  322.  
  323.        // Find the end of the filename
  324.        q = _fstrchr(p, ' ');
  325.  
  326.        if (q != NULL)
  327.           {
  328.           // Copy the filename into the temp buffer
  329.           _fstrncpy(&szBuf[x], p, (WORD) (q - p));
  330.           }
  331.        else
  332.           {
  333.           // Copy the filename (remainder of string) into the temp buffer
  334.           _fstrcpy(&szBuf[x], p);
  335.           }
  336.        }
  337.  
  338.     if (szPathName != NULL)
  339.        {
  340.        // If the user passed an address, copy the string into its buffer
  341.        _fstrncpy(szPathName, szBuf, wMaxLen);
  342.        szPathName[wMaxLen - 1] = 0;    // Force zero-termination
  343.        }
  344.  
  345.     return(lstrlen(szBuf)); // Returns length of string
  346. }
  347.  
  348.  
  349.  
  350.  
  351. /****************************************************************************/
  352. /**********************                            **************************/
  353. /********************** DROP-FILE SERVER FUNCTIONS **************************/
  354. /**********************                            **************************/
  355. /****************************************************************************/
  356.  
  357. typedef struct {
  358.         WORD  wSize;                            // Size of data structure
  359.         POINT ptMousePos;                       // Position of mouse cursor
  360.         BOOL  fInNonClientArea;                 // Was the mouse in the
  361.                                                 // window's non-client area
  362. } DROPFILESTRUCT, FAR *LPDROPFILESTRUCT;
  363.  
  364.  
  365. HDROP FAR DragCreateFiles (LPPOINT lpptMousePos,
  366.                            BOOL fInNonClientArea)
  367. {
  368.  
  369.     HGLOBAL hDrop;
  370.     LPDROPFILESTRUCT lpDropFileStruct;
  371.  
  372.     // GMEM_SHARE must be specified because the block will
  373.     // be passed to another application
  374.     hDrop = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
  375.                         sizeof(DROPFILESTRUCT) + 1);
  376.  
  377.     // If unsuccessful, return NULL
  378.     if (hDrop == NULL) return(hDrop);
  379.  
  380.     // Lock block and initialize the data members
  381.     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
  382.     lpDropFileStruct->wSize = sizeof(DROPFILESTRUCT);
  383.     lpDropFileStruct->ptMousePos = *lpptMousePos;
  384.     lpDropFileStruct->fInNonClientArea = fInNonClientArea;
  385.     GlobalUnlock(hDrop);
  386.     return(hDrop);
  387. }
  388.  
  389.  
  390. HDROP FAR DragAppendFile (HGLOBAL hDrop, LPCSTR szPathname)
  391. {
  392.     LPDROPFILESTRUCT lpDropFileStruct;
  393.     LPCSTR lpCrnt;
  394.     WORD wSize;
  395.  
  396.     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
  397.  
  398.     // Point to first pathname in list
  399.     lpCrnt = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
  400.  
  401.     // Search for a pathname were first byte is a zero byte
  402.     while (*lpCrnt)         // While the 1st char of path is non-zero
  403.        {
  404.        while (*lpCrnt) lpCrnt++;   // Skip to zero byte
  405.        lpCrnt++;
  406.        }
  407.  
  408.     // Calculate current size of block
  409.     wSize = (WORD) (lpCrnt - (LPSTR) lpDropFileStruct + 1);
  410.     GlobalUnlock(hDrop);
  411.  
  412.     // Increase block size to accommodate new pathname being appended
  413.     hDrop = GlobalReAlloc(hDrop, wSize + lstrlen(szPathname) + 1,
  414.                           GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE);
  415.  
  416.     // Return NULL if insufficient memory
  417.     if (hDrop == NULL) return(hDrop);
  418.  
  419.     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock(hDrop);
  420.     // Append the pathname to the block
  421.     lstrcpy((LPSTR) lpDropFileStruct + wSize - 1, szPathname);
  422.     GlobalUnlock(hDrop);
  423.     return(hDrop);  // Return the new handle to the block
  424. }
  425.